package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.ObjectUtils;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author B
 * @since 2024-08-25
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final UserClient userClient;

    /*
     * 隐藏或显示指定回答或评论
     * */
    @Override
    @Transactional
    public void hiddenOrShowReply(Long id, Boolean hidden) {
        // 1.查询
        InteractionReply old = getById(id);
        if (old == null) {
            return;
        }

        // 2.隐藏回答
        InteractionReply reply = new InteractionReply();
        reply.setId(id);
        reply.setHidden(hidden);
        updateById(reply);

        // 3.隐藏评论，先判断是否是回答，回答才需要隐藏下属评论
        if (old.getAnswerId() != null && old.getAnswerId() != 0) {
            // 3.1.有answerId，说明自己是评论，无需处理
            return;
        }
        // 3.2.没有answerId，说明自己是回答，需要隐藏回答下的评论
        lambdaUpdate()
                .set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getAnswerId, id)
                .update();
    }

    /**
     * 管理端-分页查询回答或评论
     *
     * @param query
     * @param isStudent
     */
    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery query, boolean isStudent) {
        // 1.先做参数判断，问题id和回答id至少要有一个
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        if (questionId == null && answerId == null) {
            throw new BadRequestException("问题或回答id不能同时为空");
        }
        // 标记当前是查询问题下的回答
        boolean isQueryAnswer = questionId != null;
        // 2.分页查询reply
        Page<InteractionReply> page = lambdaQuery()
                .eq(isQueryAnswer, InteractionReply::getQuestionId, questionId)
                .eq(InteractionReply::getAnswerId, isQueryAnswer ? 0L : answerId)
                .eq(isStudent, InteractionReply::getHidden, false)
                .page(query.toMpPage(
                        // 先根据点赞数排序，点赞数相同，再按照创建时间排序
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false))
                );
        List<InteractionReply> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        // 3.数据处理，查询：提问者信息、回复目标信息、当前用户是否点赞
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        Set<Long> targetUserIds = new HashSet<>();
        // 3.1.统计点赞信息
        for (InteractionReply r : records) {
            if (!isStudent || !r.getAnonymity()) {
                // 如果不是匿名，则加入
                userIds.add(r.getUserId());
            }
            targetUserIds.add(r.getTargetUserId());
            answerIds.add(r.getId());
        }
        // 3.2.查询目标回复，若目标回复不是匿名，则需要查询出目标回复的用户信息
        targetUserIds.remove(0L);
        targetUserIds.remove(null);
        if (targetUserIds.size() > 0) {
            userIds.addAll(targetUserIds);
        }
        // 3.3.查询用户
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 4.处理VO
        List<ReplyVO> list = new ArrayList<>(records.size());
        for (InteractionReply r : records) {
            // 4.1.拷贝基础属性
            ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
            list.add(v);
            // 4.2.回复人信息
            if (!r.getAnonymity() || !isStudent) {
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null) {
                    v.setUserIcon(userDTO.getIcon());
                    v.setUserName(userDTO.getName());
                    v.setUserType(userDTO.getType());
                }
            }
            // 4.3.如果存在评论的目标，则需要设置目标用户信息
            if (r.getTargetReplyId() != null) {
                UserDTO targetUser = userMap.get(r.getTargetUserId());
                if (targetUser != null) {
                    v.setTargetUserName(targetUser.getName());
                }
            }
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }

    private final SearchClient searchClient;
    private final CourseClient courseClient;
    /**
     * 分页查询【回答】或【评论】列表
     */
    @Autowired
    private InteractionQuestionMapper interactionQuestionMapper;
    @Autowired
    private InteractionReplyMapper replyMapper;

    /**
     * 分页查询【回答】或【评论】列表
     */
    @Override
    public PageDTO<ReplyVO> pageQuery(ReplyPageQuery query, boolean isStudent) {
        //获取userid
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        //判断是进行问题分页查询还是进行回答分页查询
        if (ObjectUtils.isEmpty(questionId) && ObjectUtils.isEmpty(answerId)) {
            throw new BadRequestException("回答id和评论id不能同时为空");
        }
        // 标记当前是查询问题下的回答
        boolean isQueryAnswer = questionId != null;
        //进行分页查询
        Page<InteractionReply> pageResult = this.lambdaQuery()
                .eq(ObjectUtils.isNotEmpty(questionId), InteractionReply::getQuestionId, questionId)
                .eq(ObjectUtils.isNotEmpty(answerId), InteractionReply::getAnswerId, isQueryAnswer ? 0L : answerId)
                .eq(isStudent, InteractionReply::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionReply> records = pageResult.getRecords();
        if (records.isEmpty()) {
            return PageDTO.empty(pageResult);
        }
        Set<Long> userIds = new HashSet<>();
        Set<Long> answersIds = new HashSet<>();
        Set<Long> targetIds = new HashSet<>();

        for (InteractionReply record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            answersIds.add(record.getAnswerId());
            targetIds.add(record.getTargetReplyId());
        }

        // 3.3.查询用户
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 4.处理VO
        List<ReplyVO> list = new ArrayList<>(records.size());
        for (InteractionReply r : records) {
            // 4.1.拷贝基础属性
            ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
            list.add(v);
            // 4.2.回复人信息
            if (!r.getAnonymity() || !isStudent) {
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null) {
                    v.setUserIcon(userDTO.getIcon());
                    v.setUserName(userDTO.getName());
                    v.setUserType(userDTO.getType());
                }
            }
            // 4.3.如果存在评论的目标，则需要设置目标用户信息
            if (r.getTargetReplyId() != null) {
                UserDTO targetUser = userMap.get(r.getTargetUserId());
                if (targetUser != null) {
                    v.setTargetUserName(targetUser.getName());
                }
            }
        }
        return new PageDTO<>(pageResult.getTotal(), pageResult.getPages(), list);
    }

    //新增回答或者评论
    @Override
    public void saveReply(ReplyDTO reply) {
        Long userId = UserContext.getUser();

        InteractionReply interactionReply = BeanUtil.toBean(reply, InteractionReply.class);

        interactionReply.setUserId(userId);
        save(interactionReply);
        boolean isAbswer = ObjectUtils.isEmpty(reply.getAnswerId());
        if (isAbswer) {
            if (ObjectUtils.isEmpty(reply.getTargetReplyId())) {
                try {
                    interactionQuestionMapper.update(
                            new InteractionQuestion()
                                    .setLatestAnswerId(interactionReply.getId())
                                    .setAnswerTimes(+1),
                            new LambdaUpdateWrapper<InteractionQuestion>()
                                    .eq(InteractionQuestion::getId, reply.getQuestionId())
                    );
                } catch (Exception e) {
                    // 处理异常
                    System.err.println("更新问答信息时发生错误: " + e.getMessage());
                }

            } else {
                //新增评论
                //更新回答评论数量
                lambdaUpdate()
                        .setSql("reply_times = reply_times + 1")
                        .set(InteractionReply::getId, reply.getTargetReplyId())
                        .update();
            }
        }
    }
}
